home *** CD-ROM | disk | FTP | other *** search
/ Amiga Developer CD 2.1 / Amiga Developer CD v2.1.iso / Reference / Amiga_Mail_Vol2 / Archives / Plain / mj91.lha / ReadArgs / readargs.txt
Encoding:
Text File  |  1991-06-13  |  10.6 KB  |  180 lines

  1. (c)  Copyright 1991 Commodore-Amiga, Inc.   All rights reserved.
  2. The information contained herein is subject to change without notice,
  3. and is provided "as is" without warranty of any kind, either expressed
  4. or implied.  The entire risk as to the use of this information is
  5. assumed by the user.
  6.  
  7.  
  8.  
  9. Standard Command Line Parsing
  10.  
  11.  
  12. by John Orr
  13.  
  14. One of the new features in release 2.0 is system standard command line parsing.  Its presence has two benefits: it standardizes the way in which the user supplies command line arguments, making it much easier on the user, and it also removes some tedious programming (and code size) from every application that uses it.
  15.  
  16. The dos.library's ReadArgs() routine is the heart of this feature:
  17.  
  18.    struct RDArgs *rda = ReadArgs( UBYTE *argtemplate, LONG *argarray, struct RDArgs *myrda );
  19.  
  20. This function stores each argument supplied on the command line in its corresponding entry in the array of LONG words, argarray.  The format in which ReadArgs() stores each argument is based on the description of the command line supplied in the first argument, argtemplate.  This description is a C-style string containing a name for each argument.  
  21.  
  22. Each argument name in the template should be a full, descriptive name (for example ``Quick'' not ``Q'').  Each option can be prepended by an abbreviation of the form ``abbrev='' (for example ``Q=Quick'').  The argtemplate options must be delimited by commas.  Avoid using the names of common commands as keywords, otherwise the user will have to delimit them with quotes.
  23.  
  24. The ordinal position that an argument appears in the description string determines what its corresponding position in argarray is (the first argument corresponds to the first entry in argarray, the second argument corresponds to the second entry in argarray, ...).  There must be an entry in argarray for each argument in the description string so that ReadArgs() has a place to store each argument's value.
  25.  
  26. Each argument name in the template can be followed by modifiers that tell ReadArgs() the format of the argument.  The valid modifiers are:
  27.  
  28. /S - Switch.  This is considered a boolean variable.  If this option is present, ReadArgs() will set the corresponding array entry in argarray (an array of LONGs) to something besides zero.  If the option is not present, ReadArgs() will set the entry to 0.
  29.  
  30. /K - Keyword.  This means that ReadArgs() will not fill in the corresponding entry in argarray unless the keyword appears with the parameter.  For example, if the template is ``Name/K'', then unless ``Name=<string>'' or ``Name <string>'' appears in the command line, the ``Name'' entry in argarray will not be altered by ReadArgs().
  31. /N - Number.  This means the parameter is considered a decimal integer, and ReadArgs() will convert it to a LONG.  If the argument is not valid, ReadArgs() will fail.  If the option is present in the command line (and it is valid), ReadArgs() will fill in the corresponding entry with a pointer to the LONG.
  32.  
  33. /T - Toggle.  This is similar to the switch (/S) modifier, but causes the corresponding boolean (in argarray) to toggle.   For example,  if the array entry corresponding to an argtemplate of ``binary\T'' is set to something besides FALSE and the word ``binary'' appears by itself on the command line, ReadArgs() will toggle that array entry to FALSE.
  34.  
  35. /A - Always.  This modifier tells ReadArgs() that this option is required.  ReadArgs() will fail if the keyword does not appear in the command line.
  36.  
  37. /F - Final (rest of line).  If this is specified, the part of the command line that follows this option is taken as the parameter for this option, even if other option keywords appear in it.
  38.  
  39. /M - Multiple arguments.  This means the argument will take any number of strings (or integers as this modifier can be used with the /N modifier), returning them as an array of strings.  Any arguments not considered to be part of another option will be added to this option.  Only one /M should appear in a template.  Example: for a template ``Dir/M,All/S'' the command-line ``foo bar all qwe'' will set the boolean ``all'', and return an array consisting of ``foo'', ``bar'', and ``qwe''.  The entry in the array will be a pointer to an array of string pointers, the last of which will be NULL.
  40.  
  41. There is an intentional interaction between /M parameters and /A parameters.  If there are unfilled /A parameters after parsing, ReadArgs() will grab strings from the end of a previous /M parameter list to fill the /A's.  This is used for things like Copy (``From/A/M,To/A'').
  42.  
  43. If the user does not supply a non-required argument (one without the ``/A'' modifier) on the command line, ReadArgs() will leave the argument's argarray entry alone.  Before calling ReadArgs(), a program should either set the argarray entries to reasonable default values or clear them, so the application can't be confused by any garbage values left in the array.
  44.  
  45. If it is successful, ReadArgs() returns a pointer to a RDArgs structure (from <dos/rdargs.h>).  ReadArgs() uses this structure internally to control its operation.  It is possible to pass ReadArgs() a custom RDArgs structure (myrda in the ReadArgs() prototype above).  For most applications myrda will be NULL, as most applications do not need to control ReadArgs().
  46.  
  47.     struct RDArgs {
  48.         struct    CSource RDA_Source; /* Select input source */
  49.         LONG      RDA_DAList;         /* PRIVATE. */
  50.         UBYTE     *RDA_Buffer;        /* Optional string parsing space. */
  51.         LONG      RDA_BufSiz;         /* Size of RDA_Buffer (0..n) */
  52.         UBYTE     *RDA_ExtHelp;       /* Optional extended help */
  53.         LONG      RDA_Flags;          /* Flags for any required control */
  54.     };
  55.  
  56. Any successful call to ReadArgs() (even those that use a custom RDArgs structure) must be complemented with a call to FreeArgs() to free the resources that ReadArgs() allocates:
  57.  
  58.     void FreeArgs(struct RDArgs *rda);
  59.  
  60. where rda is the RDArgs structure used by ReadArgs().
  61. An application can use a custom RDArgs structure to provide an alternate command line source, an alternate temporary storage buffer, or an extended help string.  The custom RDArgs structure must be allocated with AllocDosObject() and deallocated with FreeDosObject().  See the Autodocs for more details on these functions.
  62.  
  63. The RDArgs.RDA_Source field is used to supply ReadArgs() with an alternate command line to parse.  If this field is non-NULL, ReadArgs() will use it as a pointer to a CSource structure describing the alternate command line.  The CSource structure (from <dos/rdargs.h>) is as follows:
  64.  
  65.     struct CSource {
  66.         UBYTE   *CS_Buffer;
  67.         LONG    CS_Length;
  68.         LONG    CS_CurChr;
  69.     };
  70.  
  71. Where CS_Buffer is the command line to parse, CS_Length is the length of CS_Buffer, and CS_CurChr is the position in CS_Buffer from which ReadArgs() should begin its parsing.  Normally CS_CurChr is initialized to zero.
  72.  
  73. ReadArgs() uses the RDArgs structure's RDA_DAList field for internal use.  This field must be set to NULL before ReadArgs() uses this structure.
  74.  
  75. The RDA_Buffer and RDA_BufSiz fields allow an application to supply a fixed-size buffer in which to store parsed data.  This allows the application to pre-allocate a buffer rather than requiring ReadArgs() to allocate buffer space.  If either RDA_Buffer or RDA_BufSiz is NULL, ReadArgs() assumes the application has not supplied a buffer.
  76.  
  77. RDA_ExtHelp is a text string which ReadArgs() displays if the user asks for additional help.  The user asks for additional help by typing a question mark when ReadArgs() prompts the user for input (which normally happens only after he or she types a question mark as the only argument on the command line).
  78.  
  79. RDA_Flags is a bit field used to toggle certain options of ReadArgs().  Currently, only one option is implemented, RDAF_NOPROMPT.   When set, RDAF_NOPROMPT prevents ReadArgs() from prompting the user.
  80.  
  81. The following code, ReadArgs.c, uses a custom RDArgs structure to pass a command line to ReadArgs.
  82.  
  83. ;/* ReadArgs.c - Execute me to compile me with Lattice 5.10a
  84. LC -b1 -cfistq -v -y -j73 ReadArgs.c
  85. Blink FROM LIB:c.o,ReadArgs.o TO ReadArgs LIBRARY LIB:LC.lib,LIB:Amiga.lib
  86. quit
  87. */
  88.  
  89.  
  90. #include <dos/dos.h>
  91. #include <dos/rdargs.h>
  92. #include <clib/dos_protos.h>
  93. #include <clib/alib_stdio_protos.h>
  94.  
  95.  
  96. #ifdef LATTICE
  97. int CXBRK(void) { return(0); }  /* Disable Lattice CTRL/C handling */
  98. int chkabort(void) { return(0); } 
  99. #endif
  100.  
  101. UBYTE *vers = "\0$VER: ReadArgs 1.0";
  102.  
  103. #define TEMPLATE "S=SourceFiles/A/M,D=DebugLevel/K/N,L=link/S"
  104. #define OPT_SOURCE  0
  105. #define OPT_DEBUG   1
  106. #define OPT_LINK    2
  107. #define OPT_COUNT   3
  108.  
  109. /* The array of LONGs where ReadArgs() will store the data from
  110. ** the command line arguments.  C guarantees that all the array
  111. ** entries will be set to zero.
  112. */
  113. LONG result[OPT_COUNT];
  114.  
  115. /* My custom RDArgs */
  116. struct RDArgs *myrda;
  117.  
  118. ULONG StrLen(UBYTE *);
  119.  
  120. void main(void)
  121. {
  122.     UWORD x;
  123.     UBYTE **sourcefiles;
  124.     
  125.     /* Need to ask DOS for a RDArgs structure */
  126.     if (myrda = (struct RDArgs *)AllocDosObject(DOS_RDARGS, NULL))
  127.     {
  128.         /* set up my parameters for ReadArgs() */
  129.         
  130.         /* use the following command line */
  131.         myrda->RDA_Source.CS_Buffer = "file1 file2 file3 D=1 Link file4 file5\n";
  132.         myrda->RDA_Source.CS_Length = (LONG)StrLen(myrda->RDA_Source.CS_Buffer); 
  133.         
  134.         /* parse my command line */
  135.         if (ReadArgs(TEMPLATE, result, myrda))
  136.         {
  137.             /*start printing out the results */
  138.             
  139.             /* We don't need to check if there is a value in
  140.             ** result[OPT_SOURCE] because the ReadArgs() template
  141.             ** requires (using the /A modifier) that there be
  142.             ** file names, so ReadArgs() will either fill in a
  143.             ** value or ReadArgs() will fail.
  144.             */            
  145.             sourcefiles = (UBYTE **)result[OPT_SOURCE];
  146.             /* VPrintf() is a lot like Printf() except it's in
  147.             ** ROM, and the arguments are referenced from an 
  148.             ** array rather than being extracted from the stack.
  149.             */
  150.             VPrintf("Files specified:\n", NULL);
  151.             for (x=0; sourcefiles[x]; x++)
  152.                 VPrintf("\t%s\n", (LONG *)&sourcefiles[x]);
  153.     
  154.             /* Is there something in the "DebugLevel" option?
  155.             ** If there is, print it.
  156.             */
  157.             if (result[OPT_DEBUG])
  158.                 VPrintf("Debugging Level = %ld\n", (LONG *)result[OPT_DEBUG]);
  159.  
  160.             /* If the link toggle was present, say something about it. */
  161.             if (result[OPT_LINK])
  162.                 VPrintf("linking...\n", NULL);
  163.             FreeArgs(myrda);
  164.         }
  165.         FreeDosObject(DOS_RDARGS, myrda);
  166.     }
  167. }
  168.  
  169.  
  170. ULONG StrLen(UBYTE *string)
  171. {
  172.     ULONG x = 0L;
  173.     
  174.     while (string[x++]);
  175.     return(x);
  176. }
  177.  
  178.  
  179. v
  180.